const Redis = require("ioredis")
const express = require("express")
const { v4: uuidv4 } = require("uuid")
const Day = require("dayjs")

const redis = new Redis({
	port: 6379,
	host: "120.78.161.81"
})

const app = express()
app.use(express.json())

// 扔一个漂流瓶
app.post("/", async (req, res, next) => {
	try {
		const bottle = req.body
		bottle.time = Day().format("YYYY-MM-DD HH:mm:ss")
		bottleCheck(bottle)

		// 为每个漂流瓶随机生成一个不重复的 id
		const bottleId = uuidv4()

		const type = {
			male: 0,
			female: 1
		}

		// 根据漂流瓶类型的不同将漂流瓶保存到不同的数据库
		// 主要目的是为了方便使用 Redis 中的 RANDOMKEY 命令：该命令返回当前数据库中的一个随机键，不能加任何条件
		await redis.select(type[bottle.type])

		// 将数据存为哈希
		await redis.hmset(bottleId, bottle)

		// 设置漂流瓶生存期为 1 天
		await redis.expire(bottleId, 60 * 60 * 24)

		res.status(201).json({
			code: 1,
			msg: "漂流瓶已成功丢出去"
		})
	} catch (err) {
		next(err)
	}
})

// 捡一个漂流瓶
app.get("/", async (req, res, next) => {
	try {
		const query = req.query

		const type = {
			all: Math.round(Math.random()),
			male: 0,
			femail: 1
		}

		query.type = query.type || "all"

		// 根据请求的瓶子类型到不同的数据库中取数据
		await redis.select(type[query.type])

		// 随机返回一个漂流瓶 ID
		const bottleId = await redis.randomkey()

		if (!bottleId) {
			res.status(200).json({
				code: 0,
				msg: "大海空空如也..."
			})
		}

		// 根据漂流瓶 ID 获取完整的漂流瓶信息
		const bottle = await redis.hgetall(bottleId)

		res.status(200).json({
			code: 1,
			msg: { bottleId, ...bottle }
		})

		// 从 Redis 中删除捡到的漂流瓶
		redis.del(bottleId)
	} catch (err) {
		next(err)
	}
})

// 统一处理异常
app.use((err, req, res, next) => {
	res.status(500).json({
		code: 0,
		msg: err.message
	})
})

app.listen(3000, () => {
	console.log("listen at http://localhost:3000")
})

// 校验瓶子的字段
function bottleCheck(bottle) {
	if (!["male", "female"].includes(bottle.type)) {
		throw new Error("type is either male or female")
	}
	if (!bottle.owner) {
		throw new Error("owner is required")
	}
	if (!bottle.content) {
		throw new Error("content is required")
	}
}
